#include <iostream>
#include <memory>
// class Fruit
// {
// public:
//     virtual void name() = 0;
// };
// class Apple : public Fruit
// {
// public:
//     void name() override
//     {
//         std::cout << "我是一个苹果！\n";
//     }
// };

// class Banana : public Fruit
// {
// public:
//     void name() override
//     {
//         std::cout << "我是一个香蕉！\n";
//     }
// };
// class FruitFactory
// {
// public:
//     static std::shared_ptr<Fruit> create(const std::string &name)
//     {
//         if(name == "苹果")
//         {
//             return std::make_shared<Apple>();
//         }
//         else if( name == "香蕉")
//         {
//             return std::make_shared<Banana>();
//         }
//     }
// };
// 工厂方法模式
// class FruitFactory
// {
// public:
//     virtual std::shared_ptr<Fruit> create() = 0;
// };

// class AppleFactory : public FruitFactory
// {
// public:
//     std::shared_ptr<Fruit> create() override
//     {
//         return std::make_shared<Apple>();
//     }
// };
// class BananaFactory : public FruitFactory
// {
// public:
//     std::shared_ptr<Fruit> create() override
//     {
//         return std::make_shared<Banana>();
//     }
// };

// int main()
// {
//     std::shared_ptr<FruitFactory> ff(new AppleFactory());
//     std::shared_ptr<Fruit>fruit = ff->create();
//     fruit->name();

//     ff.reset(new BananaFactory());
//     std::shared_ptr<Fruit>fruit2 = ff->create();
//     fruit2->name();

//     // std::shared_ptr<Fruit> fruit1 = FruitFactory::create("苹果");
//     // fruit1->name();
//     // std::shared_ptr<Fruit> fruit2 = FruitFactory::create("香蕉");
//     // fruit2->name();
//     return 0;
// }

// 抽象工厂模式

class Animal
{
public:
    virtual void name() = 0;
};

class Lamp : public Animal
{
public:
    void name() override
    {
        std::cout << "我是一山羊" << std::endl;
    }
};
class Dog : public Animal
{
public:
    void name() override
    {
        std::cout << "我是一小狗" << std::endl;
    }
};

class Fruit
{
public:
    virtual void name() = 0;
};
class Apple : public Fruit
{
public:
    void name() override
    {
        std::cout << "我是一个苹果！\n";
    }
};

class Banana : public Fruit
{
public:
    void name() override
    {
        std::cout << "我是一个香蕉！\n";
    }
};
class Factor
{
public:
    virtual std::shared_ptr<Fruit> getFruit(const std::string &name) = 0;
    virtual std::shared_ptr<Animal> getAnimal(const std::string &name) = 0;
};

class FruitFactory : public Factor
{
public:
    std::shared_ptr<Animal> getAnimal(const std::string &name)
    {
        // 水果工厂不需要，返回一个空的就行
        return std::shared_ptr<Animal>();
    }

    std::shared_ptr<Fruit> getFruit(const std::string &name)
    {
        // 根据不同的名字产生不同的水果
        if (name == "苹果")
        {
            return std::make_shared<Apple>();
        }
        else if (name == "香蕉")
        {
            return std::make_shared<Banana>();
        }
    }
};
class AnimalFactory : public Factor
{
public:
    std::shared_ptr<Fruit> getFruit(const std::string &name)
    {
        return std::shared_ptr<Fruit>();
    }

    std::shared_ptr<Animal> getAnimal(const std::string &name)
    {
        // 根据不同的名字产生不同的水果
        if (name == "山羊")
        {
            return std::make_shared<Lamp>();
        }
        else if (name == "小狗")
        {
            return std::make_shared<Dog>();
        }
    }
};
class FactorProducer
{
public:
    // 静态就可以直接用
    static std::shared_ptr<Factor> create(const std::string &name)
    {
        if (name == "水果")
        {
            return std::make_shared<FruitFactory>();
        }
        else if (name == "动物")
        {
            return std::make_shared<AnimalFactory>();
        }
    }
};
int main()
{
    std::shared_ptr<Factor> ff = FactorProducer::create("水果");

    std::shared_ptr<Fruit> fruit = ff->getFruit("苹果");
    fruit->name();
    std::shared_ptr<Fruit> fruit2 = ff->getFruit("香蕉");
    fruit2->name();

    std::shared_ptr<Factor> ff2 = FactorProducer::create("动物");

    
    std::shared_ptr<Animal> Animal2 = ff2->getAnimal("小狗");
    Animal2->name();
    
    std::shared_ptr<Animal> Animal = ff2->getAnimal("山羊");
    Animal->name();

}